package org.example.hypersonaltools.scene;

import javafx.animation.*;
import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Labeled;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.util.Duration;
import org.example.hypersonaltools.tool.FunctionToAnimation;
import org.example.hypersonaltools.manager.TagManager;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.function.Function;

public class OneToolScene implements FXScene {

    private Scene scene;
    private Pane root;
    private final List<ParallelTransition> parallelTransitions = new ArrayList<>();
    private static Boolean stopped = false;

    public OneToolScene() {
        root = new Pane();
        scene = new Scene(root, 800, 600);

        // 从标签管理器中获取所有工具标签名
        Map<String, Labeled> tags = TagManager.getInstance().getTags();
        List<Labeled> tagsList = new ArrayList<>(tags.values());

        int numTags = tagsList.size();
        double radius = 200;

        List<Double[]> zbs = new ArrayList<>();
        for (int i = 0; i < numTags; i++) {
            double phi = Math.acos(1 - (double) (2 * (i + 0.5)) / numTags); // 极角
            double theta = Math.PI * (1 + Math.sqrt(5)) * i; // 方位角
            double z = radius * Math.cos(phi); // z 坐标（可用于深度调整）
            zbs.add(new Double[]{radius*Math.sin(phi)*Math.cos(theta), radius*Math.sin(phi)*Math.sin(theta),z});
        }

        int maxIterations = 1000; // 最大迭代次数
        double stepSize = 0.01; // 步长
        List<Double[]> optimizedPoints = electrostaticRepulsion(zbs, radius, maxIterations, stepSize);

        for (int i = 0; i < optimizedPoints.size(); i++) {
            Labeled tag = tagsList.get(i);
            tag.setOpacity(1);
            root.getChildren().add(tag);

            Double[] coordinates = optimizedPoints.get(i);
            tag.setLayoutX(400);
            tag.setLayoutY(300 + coordinates[1]);
            // 调用封装方法
            parallelTransitions.add(createOrbitalAnimation(tag, coordinates, 200, 20, Duration.seconds(5), 100));
        }

        root.setOnMousePressed(mouseEvent -> {
            if (mouseEvent.getClickCount() == 2&&!stopped) {
                parallelTransitions.forEach(Animation::pause);
                stopped = true;
            }else if (mouseEvent.getClickCount() == 2&&stopped){
                parallelTransitions.forEach(Animation::play);
                stopped = false;
            }
        });

    }
    public static ParallelTransition createOrbitalAnimation(Region tag, Double[] coordinates,
                                                      double radius, double viewAngleDegrees,
                                                      Duration duration, double frameInterval) {
        //根据z坐标变化设置初始缩放
        Double z = coordinates[2];
        double scaleFactor = 1 + (radius - z) / radius;
        scaleFactor = Math.max(0.5, Math.min(2, scaleFactor));
        tag.setScaleX(scaleFactor);
        tag.setScaleY(scaleFactor);

        // 计算椭圆参数
        double viewAngle = Math.toRadians(viewAngleDegrees);
        double tanTheta = Math.tan(viewAngle);
        double originalRadius = Math.sqrt(Math.pow(coordinates[0], 2) + Math.pow(coordinates[2], 2));
        double semiMinorAxis = originalRadius * (1 / (1 + originalRadius * tanTheta));

        // 创建运动动画

        Function<Double, Double> xFunction = t -> originalRadius * Math.cos(t);
        Function<Double, Double> yFunction = t -> semiMinorAxis * Math.sin(t);

        // 创建缩放动画
        Function<Double, Double> scaleFunction = createScaleAnimationFunction(0.5, 2.0);

        // 构建动画时间轴
        Timeline animationX = FunctionToAnimation.createAnimation(tag.translateXProperty(), xFunction, 0, 2*Math.PI, duration, frameInterval);
        animationX.setCycleCount(Timeline.INDEFINITE);
        Timeline animationY = FunctionToAnimation.createAnimation(tag.translateYProperty(), yFunction, 0, 2*Math.PI, duration, frameInterval);
        animationY.setCycleCount(Timeline.INDEFINITE);
        Timeline scaleAnimX = FunctionToAnimation.createAnimation(tag.scaleXProperty(), scaleFunction, 0, 2*Math.PI, duration, frameInterval);
        scaleAnimX.setCycleCount(Timeline.INDEFINITE);
        Timeline scaleAnimY = FunctionToAnimation.createAnimation(tag.scaleYProperty(), scaleFunction, 0, 2*Math.PI, duration, frameInterval);
        scaleAnimY.setCycleCount(Timeline.INDEFINITE);
        // 播放组合动画
        ParallelTransition parallelTransition = new ParallelTransition(animationX, animationY, scaleAnimX,scaleAnimY);
        parallelTransition.setRate(new Random().nextDouble() + 0.1);
        parallelTransition.play();
        return parallelTransition;
    }

    // 独立缩放函数创建方法
    private static Function<Double, Double> createScaleAnimationFunction(double minScale, double maxScale) {
        return t -> {
            double adjustedAngle = t - Math.PI;
            double sine = Math.sin(adjustedAngle);
            return (maxScale - minScale) * (sine + 1)/2 + minScale;
        };
    }

    //根据斥力的分布算法
    public static List<Double[]> electrostaticRepulsion(List<Double[]> points, double radius, int maxIterations, double stepSize) {
        int numPoints = points.size();
        for (int iter = 0; iter < maxIterations; iter++) {
            // 计算每个点的排斥力
            double[][] forces = new double[numPoints][3];
            for (int i = 0; i < numPoints; i++) {
                for (int j = i + 1; j < numPoints; j++) {
                    Double[] p1 = points.get(i);
                    Double[] p2 = points.get(j);
                    double dx = p1[0] - p2[0];
                    double dy = p1[1] - p2[1];
                    double dz = p1[2] - p2[2];
                    double distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
                    double force = 1.0 / (distance * distance); // 排斥力与距离平方成反比

                    // 计算力的分量
                    forces[i][0] += force * dx / distance;
                    forces[i][1] += force * dy / distance;
                    forces[i][2] += force * dz / distance;
                    forces[j][0] -= force * dx / distance;
                    forces[j][1] -= force * dy / distance;
                    forces[j][2] -= force * dz / distance;
                }
            }

            // 更新点的位置
            for (int i = 0; i < numPoints; i++) {
                Double[] point = points.get(i);
                double fx = forces[i][0];
                double fy = forces[i][1];
                double fz = forces[i][2];

                // 更新坐标
                point[0] += stepSize * fx;
                point[1] += stepSize * fy;
                point[2] += stepSize * fz;

                // 将点重新投影到球面上
                double norm = Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
                point[0] = radius * point[0] / norm;
                point[1] = radius * point[1] / norm;
                point[2] = radius * point[2] / norm;
            }
        }
        return points;
    }

    @Override
    public Scene getScene() {
        return scene;
    }

    @Override
    public void onEnter() {
        // 动画开始时的操作
        Platform.runLater(() -> {
            for (Node node : root.getChildren()) {
            }
        });
    }

    @Override
    public void onExit() {
        // 动画结束时的操作
        Platform.runLater(() -> {
            for (Node node : root.getChildren()) {
            }
        });
    }
}


